package com.cicoding.uhfreader;


import com.cicoding.config.WebSocket;
import com.cicoding.config.ZebraUHFProperties;
import com.cicoding.domian.KufangData;
import com.cicoding.utlis.JdbcUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.uhf.alm.CabinetAlgorithm;
import com.uhf.api.cls.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;


@Slf4j
@Component
public class ReaderAsyncRead1 {

    @Resource
    private ZebraUHFProperties zebraUHFProperties;

    private ScheduledExecutorService scheduledExecutorService;
    /**
     * 读写次数
     */
    private Map<String, Integer> redNumMap = new HashMap<>();

    private ConcurrentHashMap<Integer, Integer> ipJL = new ConcurrentHashMap<>();


    @Resource
    private WebSocket webSocket;

    //初始化数据 和上次数据,常量用于做对比

    //初始化数据,之后的数据用来对比
    private Cache<String, Long> cache  = CacheBuilder.newBuilder()
            .maximumSize(5000) // 可以根据需求设置缓存大小限制，比如1000条记录
            .build();

    Cache<String, Long>  RFIDCache = CacheBuilder.newBuilder()
            .expireAfterWrite(100, TimeUnit.MINUTES)
            .build();

    Cache<String, String>  sqlData = CacheBuilder.newBuilder()
            .build();

    /**
     * 读写器是否初始化
     */
    private ConcurrentHashMap<String, Reader> readerMap = new ConcurrentHashMap<>();

    private ConcurrentHashMap<String, Reader> ipStatus = new ConcurrentHashMap<>();


    private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();



    Reader Jreader;

    CabinetAlgorithm CA;

    @Value("${uhfReadMode.antennaDwellTime}")
    private Integer antennaDwellTime;

    @Value("${uhfReadMode.maximumPower}")
    private Integer maximumPower;

    private boolean flage;

    public boolean openReader() {
        boolean isInit = false;
        scheduledExecutorService = Executors.newScheduledThreadPool(zebraUHFProperties.getConfigs().size());
        for (ZebraUHFProperties.ZebraUHF zebraUHF : zebraUHFProperties.getConfigs()) {
            isInit = initReader(zebraUHF) ? true : isInit;
        }



        return isInit;
    }

    public void checkGpi() {
        GpiInfo_ST gpist=new GpiInfo_ST();
        Reader.READER_ERR readerErr1 = Jreader.GetGPIEx(gpist);
        if (readerErr1 == Reader.READER_ERR.MT_OK_ERR){
            for(int i=0;i<gpist.gpiCount;i++){
                String stats = gpist.gpiStats[i].State+"";
                if (stats.equals("0")) {

                    ipJL.put(gpist.gpiStats[i].GpiId,gpist.gpiStats[i].State);
                }else if (null != ipJL.get(gpist.gpiStats[i].GpiId)){
                    if (null == ipStatus.get(zebraUHFProperties.getConfigs().get(0).getIP())){
                        //ipStatus.put(ip,reader);
                        webSocket.sendInfo("开始盘点","89");
                        scheduleTaskWithDelayAndClose(10);
                    }
                    ipJL.remove(gpist.gpiStats[i].GpiId);
                }
            }

        }
    }


    public  void query() throws Exception {
        Connection conn = JdbcUtils.getConnect();
        Statement stat = conn.createStatement();
        ResultSet rs = stat.executeQuery("select * from kufangxinxi");
        List<KufangData> list = new ArrayList<>();
        while (rs.next()) {
            sqlData.put(rs.getString("code"),rs.getString("name"));
        }
        JdbcUtils.close(conn, rs);
       // return list;
    }

    public void checkGpis1() {
        for (Map.Entry<String, Reader> entry : readerMap.entrySet()) {
            String ip = entry.getKey();
            Reader reader = entry.getValue();
            GpiInfo_ST gpist = new GpiInfo_ST();
            Reader.READER_ERR readerErr1 = reader.GetGPIEx(gpist);



            if (readerErr1 == Reader.READER_ERR.MT_OK_ERR) {
                for (int i = 0; i < gpist.gpiCount; i++) {
                   /* System.out.println("get gpi>>>>" + (gpist.gpiStats[i].GpiId) + ":"
                            + gpist.gpiStats[i].State +" --- ip -- " +ip
                            +" - Reader.READER_ERR.MT_OK_ERR --- " +Reader.READER_ERR.MT_OK_ERR);*/
                    String stats = gpist.gpiStats[i].State+"";
                    if (stats.equals("0")) {
                        ipJL.put(gpist.gpiStats[i].GpiId,gpist.gpiStats[i].State);
                    }else if (null != ipJL.get(gpist.gpiStats[i].GpiId)){
                        System.out.println("检测到了-开始执行");
                        if (null == ipStatus.get(ip)){
                            //ipStatus.put(ip,reader);
                            scheduleTaskWithDelayAndClose(5);
                        }
                        ipJL.remove(gpist.gpiStats[i].GpiId);
                    }
                }

            } else {
                log.error("读写器[{}]获取GPI状态出错: {}", ip, readerErr1);
            }
        }
    }


    public void checkGpis() {
        for (Map.Entry<String, Reader> entry : readerMap.entrySet()) {
            String ip = entry.getKey();
            Reader reader = entry.getValue();
            GpiInfo_ST gpist = new GpiInfo_ST();
            Reader.READER_ERR readerErr1 = reader.GetGPIEx(gpist);
            if (readerErr1 == Reader.READER_ERR.MT_OK_ERR) {
                for (int i = 0; i < gpist.gpiCount; i++) {

                   /* System.out.println("get gpi>>>>" + (gpist.gpiStats[i].GpiId) + ":"
                            + gpist.gpiStats[i].State +" --- ip -- " +ip
                            +" - Reader.READER_ERR.MT_OK_ERR --- " +Reader.READER_ERR.MT_OK_ERR);*/
                    String stats = gpist.gpiStats[i].State+"";

                   // System.out.println("--- stats -- "+ stats);
                    if (stats.equals("0")) {
                      //  System.out.println("--- tttt -- "+ ipStatus.get(ip));
                        if (null == ipStatus.get(ip)){
                         //   System.out.println("--- 55555 -- "+ stats);
                           // ipStatus.put(ip,reader);
                            scheduleTaskWithDelayAndClose(10);
                        }
                        System.out.println("get gpi>>>>" + (gpist.gpiStats[i].GpiId) + ":"
                                + gpist.gpiStats[i].State +"ip -- " +ip
                        +" - Reader.READER_ERR.MT_OK_ERR --- " +Reader.READER_ERR.MT_OK_ERR);
                    } else if (gpist.gpiStats[i].State == 1) {

                    }
                }

            } else {
                log.error("读写器[{}]获取GPI状态出错: {}", ip, readerErr1);
            }
        }
    }

    private boolean initReader(ZebraUHFProperties.ZebraUHF zebraUHF){
        String ip = zebraUHF.getIP();
        Jreader = readerMap.get(ip);

        if (Jreader != null) {
            readerMap.remove(ip);
            //startMap.remove(ip);
            Jreader.CloseReader();
        }
        Jreader = new Reader();
        // 创建读写器，传入读写器地址串口或者网口，天线口总个数
        Reader.READER_ERR er = Jreader.InitReader_Notype(zebraUHF.getIP(), zebraUHF.getPortNum());
        if (er != Reader.READER_ERR.MT_OK_ERR){
            log.error("UHF读写器[{}], 连接读写器出错: {}", ip, er);
            return false;
        }

        Jreader.addReadExceptionListener(REL);
        Jreader.addReadListener(RL);

        //获取硬件信息
        Reader.HardwareDetails val = Jreader.new HardwareDetails();
        er = Jreader.GetHardwareDetails(val);
        //获取版本信息
        Reader.ReaderVersion rdrver = Jreader.new ReaderVersion();
        Jreader.ParamGet(Reader.Mtr_Param.MTR_PARAM_READER_VERSION, rdrver);

        log.info("UHF读写器[{}], hardwareVer: {}, softwareVer: {}", ip, rdrver.hardwareVer, rdrver.softwareVer);

        int[] val2 = new int[1];
        er = Jreader.ParamGet(Reader.Mtr_Param.MTR_PARAM_READER_AVAILABLE_ANTPORTS, val2);

        //获取可配置的最大功率，最小功率
        int[] maxpower = new int[1];
        Jreader.ParamGet(Reader.Mtr_Param.MTR_PARAM_RF_MAXPOWER, maxpower);
        int[] minpower = new int[1];
        Jreader.ParamGet(Reader.Mtr_Param.MTR_PARAM_RF_MINPOWER, minpower);
        log.info("UHF读写器[{}], 最大功率: {}, 最小功率: {}", ip,  maxpower[0], minpower[0]);

        //设置最大功率
        Reader.AntPowerConf apcf = Jreader.new AntPowerConf();
        apcf.antcnt = zebraUHF.getPortNum();
        int newMaxPower = 2700; // 假设你想设置的最大功率是2200
        for (int i = 0; i < apcf.antcnt; i++) {
            Reader.AntPower jaap = Jreader.new AntPower();
            jaap.antid = i + 1;
           /* jaap.readPower = (short)maxpower[0];
            jaap.writePower = (short)maxpower[0];*/
            jaap.readPower = (short)newMaxPower;
            jaap.writePower = (short)newMaxPower;
            apcf.Powers[i] = jaap;
        }
        Reader.AntPowerConf apcf2 = Jreader.new AntPowerConf();
        er = Jreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_RF_ANTPOWER, apcf);
        er = Jreader.ParamGet(Reader.Mtr_Param.MTR_PARAM_RF_ANTPOWER, apcf2);
        for (int i = 0; i < apcf2.antcnt; i++) {
            log.info("UHF读写器[{}], 天线端口: {}, 读功率: {}, 写功率: {}", ip, apcf2.Powers[i].antid, apcf2.Powers[i].readPower, apcf2.Powers[i].writePower);
        }

        //设置北美频段
        Reader.Region_Conf rcf1 = Reader.Region_Conf.RG_NA;
        er = Jreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_FREQUENCY_REGION, rcf1);

        //设置gen2协议，可选非必要，现在模块默认为gen2协议
        Reader.Inv_Potls_ST ipst = Jreader.new Inv_Potls_ST();
        ipst.potlcnt = 1;
        ipst.potls = new Reader.Inv_Potl[1];
        for (int i = 0; i < ipst.potlcnt; i++) {
            Reader.Inv_Potl ipl = Jreader.new Inv_Potl();
            ipl.weight = 30;
            ipl.potl = Reader.SL_TagProtocol.SL_TAG_PROTOCOL_GEN2;
            ipst.potls[0] = ipl;
        }
        er = Jreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_TAG_INVPOTL, ipst);

        //设置是否检测天线，如果需要使用不可检测的天线（即无法检测天线是否连接在天线端口上）需要此项设置。
        er = Jreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_READER_IS_CHK_ANT, new int[] { 0 });

        //设置session0  值0，1，2，3   ，0用于少数标签，1用于多标签 ，2和3 不常用，（标签只读一遍，若需持续用需要配合target参数使用）
        er = Jreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_POTL_GEN2_SESSION, new int[] { 0 });

        readerMap.put(ip, Jreader);
        return true;

    }

 /*   private boolean initReader(ZebraUHFProperties.ZebraUHF zebraUHF) {
        // 创建读写器，传入读写器地址串口或者网口，天线口总个数
        // READER_ERR
        String ip = zebraUHF.getIP();
         Jreader = readerMap.get(ip);
        if (Jreader != null) {
            readerMap.remove(ip);
          //  startMap.remove(ip);
            Jreader.CloseReader();
        }
        Jreader = new Reader();
        // 创建读写器，传入读写器地址串口或者网口，天线口总个数
        Reader.READER_ERR er = Jreader.InitReader_Notype(zebraUHF.getIP(), zebraUHF.getPortNum());
        System.out.println(er.toString());
        if (er != Reader.READER_ERR.MT_OK_ERR)
            return false;
        Reader.HardwareDetails val = Jreader.new HardwareDetails();
        er = Jreader.GetHardwareDetails(val);
        //获取版本信息
        Reader.ReaderVersion rdrver = Jreader.new ReaderVersion();
        Jreader.ParamGet(Reader.Mtr_Param.MTR_PARAM_READER_VERSION, rdrver);

        System.out.println("module:" + val.module.toString() + "\r\nsoftwareVer:" +
                rdrver.softwareVer + "\r\nhardwareVer:" + rdrver.hardwareVer);
        //获取可配置的最大功率，最小功率
        int[] maxpower = new int[1];
        maxpower[0] = 0;
        Jreader.ParamGet(Reader.Mtr_Param.MTR_PARAM_RF_MAXPOWER, maxpower);
        System.out.println("max:" + maxpower[0]);
        int[] minpower = new int[1];
        minpower[0] = 0;
        Jreader.ParamGet(Reader.Mtr_Param.MTR_PARAM_RF_MINPOWER, minpower);
        System.out.println("min:" + minpower[0]);

        Reader.AntPowerConf apcf2 = Jreader.new AntPowerConf();
        er = Jreader.ParamGet(Reader.Mtr_Param.MTR_PARAM_RF_ANTPOWER, apcf2);
        for (int i = 0; i < apcf2.antcnt; i++) {
            System.out.print("antid:" + apcf2.Powers[i].antid);
            System.out.print(" rp:" + apcf2.Powers[i].readPower);
            System.out.print(" wp:" + apcf2.Powers[i].writePower);
            System.out.println();
        }

        //设置北美频段   可以根据实际修改
        Reader.Region_Conf rcf1 = Reader.Region_Conf.RG_NA;
        er = Jreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_FREQUENCY_REGION, rcf1);

        //设置是否检测天线，如果需要使用不可检测的天线（即无法检测天线是否连接在天线端口上）需要此项设置。
        er = Jreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_READER_IS_CHK_ANT, new int[]{0});
        readerMap.put(ip, Jreader);
        return true;
    }
*/
    public boolean startReadTags() {
        log.info("打开读写器");

        AtomicBoolean isStart = new AtomicBoolean(false);
        //stopMap.clear();
        for (ZebraUHFProperties.ZebraUHF zebraUHF : zebraUHFProperties.getConfigs()) {
            isStart.set(startReader(zebraUHF) || isStart.get());
        }
        return true;
    }

    public void compareCachesAndPrintMessages() {
        Map<String, Long> cacheData = cache.asMap();
        Map<String, Long> RFIDCacheData = RFIDCache.asMap();

        Iterator<Map.Entry<String, Long>> cacheIterator = cacheData.entrySet().iterator();
        while (cacheIterator.hasNext()) {
            Map.Entry<String, Long> entry = cacheIterator.next();
            String key = entry.getKey();
            if (!RFIDCacheData.containsKey(key)) {
                if (sqlData.asMap().containsKey(key)) {
                    String value = sqlData.getIfPresent(key);
                    System.out.println(key + " -  (出库) 工器具"+value);
                    webSocket.sendInfo(key + " -  (出库) 工器具"+value,"89");
                    cacheIterator.remove(); // Remove the data from cacheData
                }
            }
        }

        Iterator<Map.Entry<String, Long>> RFIDIterator = RFIDCacheData.entrySet().iterator();
        List<String> keysToAdd = new ArrayList<>();
        while (RFIDIterator.hasNext()) {
            Map.Entry<String, Long> entry = RFIDIterator.next();
            String key = entry.getKey();
            if (!cacheData.containsKey(key)) {
                if (sqlData.asMap().containsKey(key)) {
                    keysToAdd.add(key);
                    String value = sqlData.getIfPresent(key);
                    webSocket.sendInfo(key + " -  (入库) 工器具"+value,"89");
                    System.out.println(key + " -  (入库) 工器具"+value);
                }
            }
        }
        // System.out.println();

        String cache = "";

        for (Map.Entry<String, Long> entry : cacheData.entrySet()) {
            cache += entry.getKey() +" , ";
           // System.out.println("Tag: " + entry.getKey() + ", Value: " + entry.getValue());
        }
        String rfid = "";

        for (Map.Entry<String, Long> entry : RFIDCacheData.entrySet()) {
            rfid += entry.getKey() + " , ";
            //System.out.println("Tag: " + entry.getKey() + ", Value: " + entry.getValue());
        }

        System.out.println("\nRFID Cache Data: "+ cache);
        System.out.println("\nRFID rfid Data: "+ rfid);
        // Add the new keys to cacheData
        for (String key : keysToAdd) {
            cacheData.put(key, System.currentTimeMillis());
        }
        try {
        //    webSocket.sendInfo("3333","89");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        RFIDCache.invalidateAll();
    }



   /* public void compareCachesAndPrintMessages() {
        Map<String, Long> cacheData = cache.asMap();
        Map<String, Long> RFIDCacheData = RFIDCache.asMap();

        Iterator<Map.Entry<String, Long>> cacheIterator = cacheData.entrySet().iterator();
        while (cacheIterator.hasNext()) {
            Map.Entry<String, Long> entry = cacheIterator.next();
            String key = entry.getKey();
            if (!RFIDCacheData.containsKey(key)) {
                System.out.println(key + " - Entry found in cache but not in RFIDCache, needs to be removed (出库)");
                cacheIterator.remove(); // Remove the data from cacheData
            }
        }

        Iterator<Map.Entry<String, Long>> RFIDIterator = RFIDCacheData.entrySet().iterator();
        List<String> keysToAdd = new ArrayList<>();
        while (RFIDIterator.hasNext()) {
            Map.Entry<String, Long> entry = RFIDIterator.next();
            String key = entry.getKey();
            if (!cacheData.containsKey(key)) {
                keysToAdd.add(key);
                System.out.println(key + " - Entry not found in cache, needs to be added (入库)");
            }
        }

        // Add the new keys to cacheData
        for (String key : keysToAdd) {
            cacheData.put(key, System.currentTimeMillis());
        }
    }*/




    //开启读写器
  /*  public synchronized boolean startReaders(ZebraUHFProperties.ZebraUHF zebraUHF) {
        flage = false;
        // log.error("开始执行-----{} ", zebraUHF);
        String ip = zebraUHF.getIP();
        Reader Jreader = readerMap.get(ip);
        TagModel tm = new TagModel();
        tm.setGen2Target(2);// A 0，B 1，A-B 2，B-A 3
        tm.setS2_AInstruct(true);//S2->A  true 启用，false 不启用
        List<Rfmodels> lrflist = new ArrayList<Rfmodels>();
        Rfmodels rf1 = new Rfmodels();
        rf1.setCount(2);// 次数 需>=1
        rf1.setQval(-1);//-1 自动 0-15 为静态Q
        rf1.setTime(antennaDwellTime);//天线驻留时间
        rf1.setRfModel("RF_MODE_7");
        lrflist.add(rf1);
        rf1 = new Rfmodels();
        rf1.setCount(2);// 次数 需>=1
        rf1.setQval(3);//-1 自动 0-15 为静态Q
        rf1.setTime(antennaDwellTime);//天线驻留时间
        rf1.setRfModel("RF_MODE_13");
        lrflist.add(rf1);
        tm.setrflist(lrflist);
        CA = new CabinetAlgorithm(Jreader, maximumPower, tm);
        //  CabinetAlgorithm CA = new CabinetAlgorithm(Jreader, 3300, tm);
        CA.addReadExceptionListener(REL);
        CA.addReadListener(RL);

        //天线数组，数组元素为对应的物理天线号，从1开始。
        int[] ants = Arrays.asList(zebraUHF.getAntArray().split(",")).stream().mapToInt(Integer::parseInt).toArray();
        for (int i = 0; i < ants.length; i++)
            ants[i] = i + 1;
        //设置控制返回标签属性项
        int option = 0;
       // st = st + 1;
        //开始
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
        //开始盘点
        log.error("天线" + ip + "Preparationforwork {}", dateFormat.format(new Date()));
        Reader.READER_ERR re = CA.Preparationforwork(CabinetAlgorithm.IT_MODE.IT_MODE_BOXV1);
        //hashMaps.remove(ip);
       // concurrentHashMap.clear();
        //allTags_V.clear();
        log.error("天线" + ip + "AsyncStartReading_IT {}", dateFormat.format(new Date()));
      //  deredMap.put(ip, true);
        CA.AsyncStartReading_IT(CabinetAlgorithm.IT_MODE.IT_MODE_BOXV1, ants, ants.length, option);

       // startMap.put(ip, true);
        return true;
    }*/

    private boolean startReader1(ZebraUHFProperties.ZebraUHF zebraUHF) {
        String ip = zebraUHF.getIP();

        Reader Jreader = readerMap.get(ip);
        ipStatus.put(ip,Jreader);
        if (Jreader == null) {
            return false;
        }
        Reader.CustomParam_ST cpst = Jreader.new CustomParam_ST();
        cpst.ParamName="Reader/Ex10fastmode";
        byte[] vals=new byte[22];
        vals[0]=1;//注意 vals[0]=1 。
      /*  if (isEx){
            //启动专有快速模式

        }else{
            //快速模式
            vals[0]=0;//注意 vals[0]=0 将不启用Ex专有快速模式，将会使用通用快速模式。
        }*/
        vals[1]=20;
        for(int i=0;i<20;i++)
            vals[2+i]=(byte)i;
        cpst.ParamVal=vals;
        Jreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_CUSTOM, cpst);

        //初始化结BackReadOption
        BackReadOption m_BROption=new BackReadOption();
        //本例只使用天线1进行盘存，如果要使用多个天线则只需要将使用的天线编
        //号赋值到数组ants中，例如同时使用天线1和2，则代码应该改为ants[0] = 1;ants[1] = 2;antcnt = 2;
        log.info("[zebraUHF]读写器IP: {}, 端口数: {}, 天线组: {}", zebraUHF.getIP(), zebraUHF.getPortNum(), zebraUHF.getAntArray());
        String[] antsStr = zebraUHF.getAntArray().split(",");
        int antcnt = antsStr.length;
        int[] ants = new int[antcnt];
        for(int i = 0; i < antcnt; i++){
            if(StringUtils.isNotBlank(antsStr[i])){
                ants[i] = Integer.parseInt(antsStr[i]);
            }
        }
        /*是否采用高速模式（目前只有slr11xx和slr12xx系列读写器才支持）,对于
         *一般标签数量不大，速度不快的应用没有必要使用高速模式,本例没有设置
         *使用高速模式
         * */
        m_BROption.IsFastRead = true;//true 表示快速模式/高速模式,false 表示普通模式


        ///非高速盘存模式下必须要设置的参数*******************************************
        //盘存周期,单位为ms，可根据实际使用的天线个数按照每个天线需要200ms
        //的方式计算得出,如果启用高速模式则此选项没有任何意义，可以设置为
        //任意值，或者干脆不设置
        m_BROption.ReadDuration = (short)(200 * antcnt);
        //盘存周期间的设备不工作时间,单位为ms,一般可设置为0，增加设备不工作
        //时间有利于节电和减少设备发热（针对某些使用电池供电或空间结构不利
        //于散热的情况会有帮助）
        m_BROption.ReadInterval = 0;
        //****************************************************************************


        //高速盘存模式参数设置********************************************************
        //以下为选择使用高速模式才起作用的选项参,照如下设置即可,如果使能高速
        //模式，即把IsFastRead设置为true则,只需取消以下被注释的代码即可
        //*
        //高速模式下为取得最佳效果设置为0即可
        m_BROption.FastReadDutyRation = 0;
        //标签信息是否携带识别天线的编号
        m_BROption.TMFlags.IsAntennaID = true;
        //标签信息是否携带标签识别次数
        //m_BROption.TMFlags.IsReadCnt = false;
        m_BROption.TMFlags.IsReadCnt = true;
        //标签信息是否携带识别标签时的信号强度
        m_BROption.TMFlags.IsRSSI = false;
        //标签信息是否携带时间戳
        m_BROption.TMFlags.IsTimestamp = false;
        //标签信息是否携带识别标签时的工作频点
        m_BROption.TMFlags.IsFrequency = false;
        //标签信息是否携带识别标签时同时读取的其它bank数据信息,如果要获取在
        //盘存时同时读取其它bank的信息还必须设置MTR_PARAM_TAG_EMBEDEDDATA参数,
        //（目前只有slr11xx和slr12xx系列读写器才支持）
        m_BROption.TMFlags.IsEmdData = false;
        //保留字段，可始终设置为0
        m_BROption.TMFlags.IsRFU = false;
        //*/
        Reader.READER_ERR er = Jreader.StartReading(ants, antcnt, m_BROption);
        if (er != Reader.READER_ERR.MT_OK_ERR){
            log.error("UHF读写器[{}], 以事件启动读标签出错: {}", ip, er);
            return false;
        }
        //  startMap.put(ip, true);
        return true;
    }


    private boolean startReader(ZebraUHFProperties.ZebraUHF zebraUHF) {
        String ip = zebraUHF.getIP();

        Reader Jreader = readerMap.get(ip);
        ipStatus.put(ip,Jreader);
        if (Jreader == null) {
            return false;
        }
        Reader.CustomParam_ST cpst = Jreader.new CustomParam_ST();
        cpst.ParamName="Reader/Ex10fastmode";
        byte[] vals=new byte[22];
        vals[0]=0;//注意 vals[0]=1 。
      /*  if (isEx){
            //启动专有快速模式

        }else{
            //快速模式
            vals[0]=0;//注意 vals[0]=0 将不启用Ex专有快速模式，将会使用通用快速模式。
        }*/
        vals[1]=20;
        for(int i=0;i<20;i++)
            vals[2+i]=(byte)i;
        cpst.ParamVal=vals;
        Jreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_CUSTOM, cpst);

        //初始化结BackReadOption
        BackReadOption m_BROption=new BackReadOption();
        //本例只使用天线1进行盘存，如果要使用多个天线则只需要将使用的天线编
        //号赋值到数组ants中，例如同时使用天线1和2，则代码应该改为ants[0] = 1;ants[1] = 2;antcnt = 2;
        log.info("[zebraUHF]读写器IP: {}, 端口数: {}, 天线组: {}", zebraUHF.getIP(), zebraUHF.getPortNum(), zebraUHF.getAntArray());
        String[] antsStr = zebraUHF.getAntArray().split(",");
        int antcnt = antsStr.length;
        int[] ants = new int[antcnt];
        for(int i = 0; i < antcnt; i++){
            if(StringUtils.isNotBlank(antsStr[i])){
                ants[i] = Integer.parseInt(antsStr[i]);
            }
        }
        /*是否采用高速模式（目前只有slr11xx和slr12xx系列读写器才支持）,对于
         *一般标签数量不大，速度不快的应用没有必要使用高速模式,本例没有设置
         *使用高速模式
         * */
        m_BROption.IsFastRead = true;//true 表示快速模式/高速模式,false 表示普通模式


        ///非高速盘存模式下必须要设置的参数*******************************************
        //盘存周期,单位为ms，可根据实际使用的天线个数按照每个天线需要200ms
        //的方式计算得出,如果启用高速模式则此选项没有任何意义，可以设置为
        //任意值，或者干脆不设置
        m_BROption.ReadDuration = (short)(200 * antcnt);
        //盘存周期间的设备不工作时间,单位为ms,一般可设置为0，增加设备不工作
        //时间有利于节电和减少设备发热（针对某些使用电池供电或空间结构不利
        //于散热的情况会有帮助）
        m_BROption.ReadInterval = 0;
        //****************************************************************************


        //高速盘存模式参数设置********************************************************
        //以下为选择使用高速模式才起作用的选项参,照如下设置即可,如果使能高速
        //模式，即把IsFastRead设置为true则,只需取消以下被注释的代码即可
        //*
        //高速模式下为取得最佳效果设置为0即可
        m_BROption.FastReadDutyRation = 0;
        //标签信息是否携带识别天线的编号
        m_BROption.TMFlags.IsAntennaID = true;
        //标签信息是否携带标签识别次数
        //m_BROption.TMFlags.IsReadCnt = false;
        m_BROption.TMFlags.IsReadCnt = true;
        //标签信息是否携带识别标签时的信号强度
        m_BROption.TMFlags.IsRSSI = false;
        //标签信息是否携带时间戳
        m_BROption.TMFlags.IsTimestamp = false;
        //标签信息是否携带识别标签时的工作频点
        m_BROption.TMFlags.IsFrequency = false;
        //标签信息是否携带识别标签时同时读取的其它bank数据信息,如果要获取在
        //盘存时同时读取其它bank的信息还必须设置MTR_PARAM_TAG_EMBEDEDDATA参数,
        //（目前只有slr11xx和slr12xx系列读写器才支持）
        m_BROption.TMFlags.IsEmdData = false;
        //保留字段，可始终设置为0
        m_BROption.TMFlags.IsRFU = false;
        //*/
        Reader.READER_ERR er = Jreader.StartReading(ants, antcnt, m_BROption);
        if (er != Reader.READER_ERR.MT_OK_ERR){
            log.error("UHF读写器[{}], 以事件启动读标签出错: {}", ip, er);
            return false;
        }
      //  startMap.put(ip, true);
        return true;
    }

    /**
     * 标签监听
     */
    ReadListener RL = new ReadListener() {
        @Override
        public void tagRead(Reader r, final Reader.TAGINFO[] tag) {
            // TODO Auto-generated method stub
            Vector<String> code1 = new Vector<String>();
            for (Reader.TAGINFO taginfo : tag) {
                String code = Reader.bytes_Hexstr(taginfo.EpcId);
               // checkGpi();
                SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
                //concurrentHashMap.put(code, dateFormat1.format(new Date()));
               // hashMaps.put(r.GetReaderAddress(), concurrentHashMap);
                long timeMillis = System.currentTimeMillis();
                  if(flage){
                      cache.put(code, timeMillis);
                      log.error("--首轮打印标签---- {} ",code);
                   }else{
                      RFIDCache.put(code,timeMillis);
                  }


                //log.error("这个是什么呢 {} ",code);
                //  code1.add(code);
                //concurrentHashMap.put(r.GetReaderAddress(),code1);
               // handleTags.handleTag(code);
            }
        }
    };

   /* ReadExceptionListener REL = new ReadExceptionListener() {

        @Override
        public void tagReadException(Reader r, Reader.READER_ERR re, String errmsg) {
            String address = r.GetReaderAddress();

            log.error("[zebraUHF]读写器[{}]异常信息: {} ", address, re);
            //判断是否异常发生过于频繁
            if (Reader.READER_ERR.MT_CMD_FAILED_ERR == re || Reader.READER_ERR.MT_CMD_NO_TAG_ERR == re) {
                return;
            }

            ZebraUHFProperties.ZebraUHF readerZebraUHF = null;
            for (ZebraUHFProperties.ZebraUHF zebraUHF : zebraUHFProperties.getConfigs()) {
                if (address.equals(zebraUHF.getIP())) {
                    readerZebraUHF = zebraUHF;
                }
            }
            if (readerZebraUHF == null) {
                return;
            }
            //尝试重新连接读写器并启动盘存操作
            boolean reConnect = false;
            r.AsyncStopReading_IT();

        }
    };*/

    ReadExceptionListener REL = (r, re) -> {
        String address =  r.GetReaderAddress();
        //如果需要可在此处记录异常日志
        log.error("[zebraUHF]读写器[{}]异常信息: {} ", address, re);
        //判断是否异常发生过于频繁
        /*if (rechecker.IsTrigger()) {
            log.error("[zebraUHF]读写器[{}]异常太过频繁,错误信息: {}", address, re);
            return;
        } else {
            rechecker.AddErr();
        }*/
        if(Reader.READER_ERR.MT_CMD_FAILED_ERR == re || Reader.READER_ERR.MT_CMD_NO_TAG_ERR == re){
            return;
        }

        ZebraUHFProperties.ZebraUHF readerZebraUHF = null;
        for(ZebraUHFProperties.ZebraUHF zebraUHF : zebraUHFProperties.getConfigs()){
            if(address.equals(zebraUHF.getIP())){
                readerZebraUHF = zebraUHF;
            }
        }
        if(readerZebraUHF == null){
            return;
        }
        //尝试重新连接读写器并启动盘存操作
        boolean reConnect = false;

        while(!reConnect) {
            log.info("ReadExceptionListener [zebraUHF]读写器[{}]正在进行重连......", address);
            if (initReader(readerZebraUHF)) {
                log.info("ReadExceptionListener [zebraUHF]读写器[{}]重连成功......", address);
                // 判断是否开启读标签
              /*  if(InventoryRecordDetailService.isStartScan()){
                    if (startReader(readerZebraUHF)) {
                        log.info("ReadExceptionListener [zebraUHF]读写器[{}]开启读取标签成功......",address);
                        reConnect = true;
                    }
                }else{
                    reConnect = true;
                }*/
            }
            if (!reConnect) {
                log.error("[zebraUHF]读写器[{}]重连失败, 5s后重新连接! ", address);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    log.error(e.getMessage());
                }
            }
        }
    };


    public boolean stopReadTags() {
        log.error("停止盘存");
        for (String ip : readerMap.keySet()) {
            Reader rdr = readerMap.get(ip);
            if (rdr != null && rdr.StopReading() != Reader.READER_ERR.MT_OK_ERR) {
                // log.error("UHF读写器[{}], 停止盘存失败！", ip);
            }
            ipStatus.remove(ip);
           // startMap.remove(ip);
           // stopMap.put(ip, true);
           /* if (schedule != null) {
                //  log.error("停止盘存", ip);
                schedule.cancel(true);
            }*/
            //停止
            rdr.AsyncStopReading_IT();
        }
        //startMap.clear();
        return true;
    }


    public void scheduleTaskWithDelayAndClose(int delayInSeconds) {
        flage = false;
        executor.schedule(() -> {
            try {
                // 在延迟之前执行关闭方法
               // System.out.println("执行关闭其他方法...");
                webSocket.sendInfo("开始盘点","89");
                startReader(zebraUHFProperties.getConfigs().get(0));

                // 延迟指定秒数后执行任务
                executor.schedule(() -> {
                    // 执行需要延迟执行的任务
                    compareCachesAndPrintMessages();
                  //  System.out.println("执行延迟任务...");
                    webSocket.sendInfo("结束盘点","89");
                    stopReadTags();
                }, delayInSeconds, TimeUnit.SECONDS);
            } catch (Exception e) {
                // 处理异常
                e.printStackTrace();
            }
        }, 0, TimeUnit.SECONDS);
    }

    public void scheduleTaskWithDelay(int delayInSeconds) {
        flage = true;
        executor.schedule(() -> {
            try {
                // 在延迟之前执行关闭方法
                // System.out.println("执行关闭其他方法...");
                startReader(zebraUHFProperties.getConfigs().get(0));
                executor.schedule(() -> {
                    // 执行需要延迟执行的任务
                    stopReadTags();
                }, delayInSeconds, TimeUnit.SECONDS);
            } catch (Exception e) {
                // 处理异常
                e.printStackTrace();
            }
        }, 0, TimeUnit.SECONDS);
    }







}
